package cn.ghostcloud.demo4.service;

import cn.ghostcloud.demo4.common.core.domain.req.GenDTEDReq;
import cn.ghostcloud.demo4.common.core.domain.req.GetProgressReq;
import cn.ghostcloud.demo4.common.core.domain.vo.GenerateProgressVO;
import cn.ghostcloud.demo4.common.core.exception.ServiceException;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RuntimeUtil;
import cn.hutool.core.util.StrUtil;
import lombok.SneakyThrows;
import org.springframework.stereotype.Service;

import java.io.*;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Service
public class GenerateService {

    private final String CONTAINER_NAME = "gen_dem_tiles";

    /**
     * 生成高程瓦片
     *
     * @param genDTEDReq
     * @throws InterruptedException
     */
    public String genDTED(GenDTEDReq genDTEDReq) throws InterruptedException {
        String uuid = merge(genDTEDReq);
        genTerrain(genDTEDReq, uuid);
        return uuid;
    }

    private String merge(GenDTEDReq genDTEDReq) throws InterruptedException {
        String fileDir = genDTEDReq.getFileDir();
        String outputDir = genDTEDReq.getOutputDir();
        Assert.isTrue(FileUtil.exist(fileDir) || !FileUtil.isDirectory(fileDir), "目录不存在");
        boolean exist = false;
        for (String fileName : FileUtil.listFileNames(fileDir)) {
            if (StrUtil.endWithAnyIgnoreCase(fileName, ".tif")) {
                exist = true;
            }
            if (StrUtil.endWithAnyIgnoreCase(fileName, "_id")) {
                FileUtil.del(fileDir + File.separator + fileName);
                Process process = RuntimeUtil.exec("docker stop " + fileName);
                process.waitFor();
            }
        }
        Assert.isTrue(exist, "文件夹中不存在tif文件");
        String uuid = IdUtil.fastSimpleUUID() + "_id";
        String filePath = fileDir.concat(File.separator).concat(uuid);
        FileUtil.touch(filePath);
        FileUtil.appendUtf8Lines(ListUtil.of("fileDir=" + fileDir), new File(filePath));
        FileUtil.appendUtf8Lines(ListUtil.of("outputDir=" + outputDir), new File(filePath));
        fileDir = fileDir.replaceAll("/", "//");
        String[] command = {"docker", "run", "--rm", "-v", fileDir + ":/data/dem", "ghcr.io/tum-gis/ctb-quantized-mesh", "bash", "-c", "\"cd /data/dem && gdalbuildvrt tiles.vrt *.tif\""};
        Process process = RuntimeUtil.exec(command);
        process.waitFor();
        String string = IoUtil.read(process.getInputStream()).toString();
        System.out.println(string);
        if (!string.contains("done")) {
            throw new ServiceException("生成出错");
        }
        return uuid;
    }

    private void genTerrain(GenDTEDReq genDTEDReq, String uuid) {
        Assert.isTrue(FileUtil.exist(genDTEDReq.getFileDir()), "目录不存在");
        try {
            FileUtil.del(genDTEDReq.getOutputDir().concat(File.separator).concat("tiles_output.txt"));
            FileUtil.del(genDTEDReq.getOutputDir().concat(File.separator).concat("json_output.txt"));
        } catch (Exception e) {
            e.printStackTrace();
        }
        new Thread(() -> {
            try {
                Process process = RuntimeUtil.exec("docker run --rm --name " + uuid + " " +
                        "-v " + genDTEDReq.getOutputDir() + ":/data/tiles " +
                        "-v " + genDTEDReq.getFileDir() + ":/data/dem ghcr.io/tum-gis/ctb-quantized-mesh " +
                        "bash -c \"cd /data/tiles " +
                        "&& ctb-tile -c 8 -s 10 -C -N -f Mesh -o ./ /data/dem/tiles.vrt > tiles_output.txt" +
                        "&& ctb-tile -c 8 -s 10 -C -N -f Mesh -l -o ./ /data/dem/tiles.vrt > json_output.txt\"");
                process.waitFor();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }).start();
    }

    /**
     * 获取生成进度
     *
     * @return
     */
    public GenerateProgressVO getProgress(GetProgressReq getProgressReq) throws FileNotFoundException, InterruptedException {
        GenerateProgressVO generateProgressVO = new GenerateProgressVO();
        generateProgressVO.setStatus(0);
        generateProgressVO.setProgress(0);
        if (!FileUtil.exist(getProgressReq.getOutputDir())) {
            FileUtil.mkdir(getProgressReq.getOutputDir());
        }
        String line;
        try {
            RandomAccessFile r = new RandomAccessFile(getProgressReq.getOutputDir().concat(File.separator).concat("tiles_output.txt"), "r");
            line = FileUtil.readLine(r, Charset.defaultCharset());
            r.close();
            if (ObjectUtil.isNotEmpty(line)) {
                if (line.endsWith("done.")) {
                    generateProgressVO.setStatus(1);//已完成
                    generateProgressVO.setProgress(100);
                    return generateProgressVO;
                } else {
                    Process process = RuntimeUtil.exec("docker ps -a --format \"{{.Names}}\"");
                    process.waitFor();
                    String string = IoUtil.read(process.getInputStream()).toString();
                    if (!string.contains(getProgressReq.getUuid())) {
                        generateProgressVO.setStatus(2);
                        return generateProgressVO;
                    }
                }
                Pattern pattern = Pattern.compile("\\d+");
                Matcher matcher = pattern.matcher(line);
                String lastNumber = "0";
                while (matcher.find()) {
                    lastNumber = matcher.group();
                }
                generateProgressVO.setProgress(Integer.parseInt(lastNumber));
            }
        } catch (Exception e) {
            return generateProgressVO;
        }
        return generateProgressVO;
    }

    /**
     * 停止生成
     *
     * @param uuid
     * @throws InterruptedException
     */
    public void stopGenerate(String uuid) throws InterruptedException {
        Process process = RuntimeUtil.exec("docker stop " + uuid);
        process.waitFor();
//        InputStream inputStream = process.getInputStream();
    }
}
